﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace JoinBoxCurrency
{
    public static partial class FileTool
    {
        /// <summary>
        /// 将文件转换成byte[] 数组  File.ReadAllBytes
        /// </summary>
        /// <param name="fileUrl">文件路径文件名称</param>
        /// <returns>byte[]</returns>
        public static byte[] GetFileData(string fileUrl)
        {
            var fs = new FileStream(fileUrl, FileMode.Open, FileAccess.Read);
            try
            {
                byte[] buffur = new byte[fs.Length];
                fs.Read(buffur, 0, (int)fs.Length);

                return buffur;
            }
            catch (Exception ex)
            {
                return null;
            }
            finally
            {
                if (fs != null)
                {
                    //关闭资源
                    fs.Close();
                }
            }
        }


        /// <summary>
        /// 将文件转换成byte[] 数组
        /// </summary>
        /// <param name="fileUrl">文件路径文件名称</param>
        /// <returns>byte[]</returns>
        public static byte[] AuthGetFileData(string fileUrl)
        {
            using (var fs = new FileStream(fileUrl, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                byte[] buffur = new byte[fs.Length];
                using (BinaryWriter bw = new BinaryWriter(fs))
                {
                    bw.Write(buffur);
                    bw.Close();
                }
                return buffur;
            }
        }
    }

    public static partial class FileTool
    {
        /// <summary>
        /// 删除母目录下所有文件
        /// </summary>
        /// <param name="pathDel">路径</param>
        /// <param name="progressBar1">进度条</param>
        public static bool DelPath(string pathDel, ProgressBar progressBar1 = null)
        {
            try
            {
                pathDel = StringTool.DelPathLastSlash(pathDel);
                string pathUp = StringTool.PathHigherLevel(pathDel);
                //删除所有子文件和子目录
                DelDirectory(pathDel, progressBar1);
                //子目录和文件数都是0,才能删除母文件夹
                if (Directory.GetDirectories(pathUp).Length == 0 &&
                    Directory.GetFiles(pathUp).Length == 0)
                {
                    var dir = new DirectoryInfo(pathUp);
                    DelDirectory(dir, progressBar1);//删除目录
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 递归子目录
        /// </summary>
        /// <param name="pathDel">来源</param>
        /// <returns>是否成功</returns>
         static bool DelDirectory(string pathDel, ProgressBar progressBar1 = null)
        {
            bool flag = false;
            DirectoryInfo dir = new DirectoryInfo(pathDel);//目录
            var dirs = dir.GetDirectories(); //子目录  
            if (dirs.Length > 0)
            {
                foreach (var dir2 in dirs)//先处理子目录的文件
                {
                    //子目录如果是文件夹,就嵌套进去
                    var attr = File.GetAttributes(dir2.FullName);
                    if (attr == FileAttributes.Directory)
                    {
                        DelDirectory(dir2.FullName, progressBar1);//递归进去删除目录                     
                    }
                    else
                    {
                        DelDirectory(dir2, progressBar1);//删除目录
                    }
                }
            }
            DelDirectory(dir, progressBar1);//删除目录 
            return flag;
        }
        /// <summary>
        /// 删除目录和文件
        /// </summary>
        /// <param name="dir2"></param>
        static void DelDirectory(DirectoryInfo dir2, ProgressBar progressBar1 = null)
        {
            var files = dir2.GetFiles();//获取所有文件
            if (files.Length > 0)
            {
                foreach (FileInfo file in files)//遍历所有文件
                {
                    DelFile(file, progressBar1);//删除文件并修改进度条
                }
            }
            dir2.Attributes = FileAttributes.Normal; //设置为普通目录
            dir2.Delete(true);
        }
        /// <summary>
        /// 删除单个文件,修改进度条
        /// </summary>
        /// <param name="dir">目录</param>
        /// <param name="progressBar1">进度条</param>
        public static bool DelFile(string file, ProgressBar progressBar1 = null)
        {
            FileInfo fileInfo = new FileInfo(file);
            return DelFile(fileInfo, progressBar1);
        }
        /// <summary>
        /// 删除文件,修改进度条
        /// </summary>
        /// <param name="file">文件</param>
        /// <param name="progressBar1">进度条</param>
        /// <returns></returns>
        static bool DelFile(FileInfo file, ProgressBar progressBar1 = null)
        {
            try
            {
                if (file.Exists)
                {
                    file.Attributes = FileAttributes.Normal; //设置为普通文件          
                    //计算进度条
                    FileStream delf = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);//以只读方式打开源文件                  
                    if (progressBar1 != null)
                    {
                        int a = progressBar1.Value - Jisuan(delf, TranSize);
                        if (progressBar1.Minimum < a)
                        {
                            progressBar1.Value = a;
                        }
                        else
                        {
                            progressBar1.Value = progressBar1.Minimum;
                        }
                    }
                    delf.Close();
                    delf.Dispose();
                    file.Delete();
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
    }
    public static partial class FileTool
    {
        /// <summary>
        /// 复制文件到文件,文件到路径,路径到路径
        /// </summary>
        /// <param name="sPath"></param>
        /// <param name="dPath"></param> 
        /// <param name="progressBar1">进度条</param> 
        /// <returns></returns>
        public static bool Copy(string sPath, string dPath, ProgressBar progressBar1 = null)
        {
            bool fa = false;
            if (sPath.Length - 1 > 0 && sPath.Length - 1 > 0)
            {
                sPath = sPath.Trim();
                while (sPath[sPath.Length - 1] == '\\')
                {
                    sPath = sPath.Substring(0, sPath.Length - 1);
                }
                dPath = dPath.Trim();
                while (dPath[dPath.Length - 1] == '\\')
                {
                    dPath = dPath.Substring(0, dPath.Length - 1);
                }
                if (File.Exists(sPath)) //来源是文件,复制到路径
                {
                    fa = CopyOneFileToDirectory(sPath, dPath, progressBar1);
                }
                else if (Directory.Exists(sPath)) //来源是路径,复制到路径
                {
                    fa = CopyDirectoryToDirectory(sPath, dPath, progressBar1);
                }
                else
                {
                    fa = false;
                }
            }
            return fa;
        }
        /// <summary>
        /// 递归拷贝所有子路径
        /// </summary>
        /// <param name="sPath">来源</param>
        /// <param name="dPath">目标</param>
        /// <param name="progressBar1">进度条</param> 
        /// <returns>true成功false不成功</returns>    
        private static bool CopyDirectoryToDirectory(string sPath, string dPath, ProgressBar progressBar1 = null)
        {
            NewFolder(dPath);
            var dir = new DirectoryInfo(sPath);//当前路径 
            bool flag = CopyAllFileToDirectory(dir, dPath, progressBar1);
            if (flag)
            {
                try
                {
                    foreach (var 来源子路径文件夹名 in dir.GetDirectories())//获取所有子路径
                    {
                        string 来源子路径的完整路径 = 来源子路径文件夹名.FullName;
                        string 目标子路径的完整路径 = 来源子路径的完整路径.Replace(sPath, dPath);
                        NewFolder(目标子路径的完整路径);
                        CopyAllFileToDirectory(来源子路径文件夹名, 目标子路径的完整路径, progressBar1);
                        CopyDirectoryToDirectory(来源子路径的完整路径, 目标子路径的完整路径, progressBar1);
                    }
                }
                catch
                {
                    flag = false;
                }
            }
            else
            {
                flag = false;
            }
            return flag;
        }
        /// <summary>
        /// 复制路径下所有文件到目标路径
        /// </summary>
        /// <param name="sPath">来源路径</param>
        /// <param name="dPath">目标路径</param>
        private static bool CopyAllFileToDirectory(DirectoryInfo sPath, string dPath, ProgressBar progressBar1 = null)
        {
            try
            {
                var files = sPath.GetFiles();//获取所有文件 
                if (files.Length > 0)
                {
                    foreach (FileInfo file in files)//遍历所有文件
                    {
                        file.Attributes = FileAttributes.Normal; //设置为普通文件
                        string sFile = file.FullName;//文件的全路径
                        string dFile = sFile.Replace(sPath.FullName, dPath);//sFile完整路径 和 前缀路径 差异=文件名,接到dPath后面
                        SFileToDFile(sFile, dFile, progressBar1);
                    }
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 复制路径下某个文件到路径
        /// </summary>
        /// <param name="sFile">文件,要完整路径</param>
        /// <param name="dPath">目标路径</param>
        /// <param name="overwrite">是否覆盖文件</param>
        /// <returns></returns>
        private static bool CopyOneFileToDirectory(string sFile, string dPath, ProgressBar progressBar1 = null)
        {
            bool fa;
            try
            {
                NewFolder(dPath);
                string dFile = Path.Combine(dPath, Path.GetFileName(sFile));
                fa = SFileToDFile(sFile, dFile, progressBar1);
            }
            catch
            {
                fa = false;
            }
            return fa;
        }
        /// <summary>
        /// 复制文件到文件
        /// </summary>
        /// <param name="sFile"></param>
        /// <param name="dFile"></param>
        /// <param name="progressBar1">进度条</param>
        /// <returns></returns>
        public static bool SFileToDFile(string sFile, string dFile, ProgressBar progressBar1 = null)
        {
            //多线程占用文件
            // https://www.cnblogs.com/Tench/p/CSharpSimpleFileWriteLock.html
            // https://www.cnblogs.com/kongyiyun/archive/2011/11/15/2249108.html
            try
            {
                //实例化源文件FileStream类
                FileStream formerOpenStream = new FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);//ReadWrite 共享也可以打开 
                //实例化目标文件FileStream类 
                FileStream toFileOpenStream;
                try
                {
                    //创建目的文件，如果已存在将被覆盖
                    var fileToCreate = new FileStream(dFile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                    fileToCreate.Close();   //关闭所有fileToCreate的资源
                    fileToCreate.Dispose(); //释放所有fileToCreate的资源               
                }
                catch (Exception ex)
                {
                    MessageBox.Show("SFileToDFile 2\n" + ex.Message);
                    return false;
                }
                try
                {
                    toFileOpenStream = new FileStream(dFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);//以写方式打开目的文件
                    int FileSize; //每次要拷贝的文件的大小
                    if (TranSize < formerOpenStream.Length)  //如果分段拷贝，即每次拷贝内容小于文件总长度
                    {
                        byte[] buffer = new byte[TranSize]; //根据传输的大小，定义一个字节数组，用来存储传输的字节
                        int copied = 0;//记录传输的大小
                        int tem_n = 1;//设置进度栏中进度的增加个数
                        while (copied <= ((int)formerOpenStream.Length - TranSize))
                        {
                            FileSize = formerOpenStream.Read(buffer, 0, TranSize);//从0开始读到buffer字节数组中，每次最大读TranSize
                            formerOpenStream.Flush();   //清空缓存
                            toFileOpenStream.Write(buffer, 0, TranSize); //向目的文件写入字节
                            toFileOpenStream.Flush();//清空缓存
                            toFileOpenStream.Position = formerOpenStream.Position; //是源文件的目的文件流的位置相同
                            copied += FileSize; //记录已经拷贝的大小
                            if (progressBar1 != null)
                            {
                                int a = progressBar1.Value + tem_n;//增加进度栏的进度块 
                                if (progressBar1.Maximum > a)
                                {
                                    progressBar1.Value = a;
                                }
                                else
                                {
                                    progressBar1.Value = progressBar1.Maximum;
                                }
                            }
                        }
                        int leftSize = (int)formerOpenStream.Length - copied; //获取剩余文件的大小
                        FileSize = formerOpenStream.Read(buffer, 0, leftSize); //读取剩余的字节
                        formerOpenStream.Flush();
                        toFileOpenStream.Write(buffer, 0, leftSize); //写入剩余的部分
                        toFileOpenStream.Flush();
                    }
                    else //如果整体拷贝，即每次拷贝内容大于文件总长度
                    {
                        byte[] buffer = new byte[formerOpenStream.Length];
                        formerOpenStream.Read(buffer, 0, (int)formerOpenStream.Length);
                        formerOpenStream.Flush();
                        toFileOpenStream.Write(buffer, 0, (int)formerOpenStream.Length);
                        toFileOpenStream.Flush();
                        if (progressBar1 != null)
                        {
                            int a = progressBar1.Value + Jisuan(formerOpenStream, TranSize);//增加进度栏的进度块 
                            if (progressBar1.Maximum > a)
                            {
                                progressBar1.Value = a;
                            }
                            else
                            {
                                progressBar1.Value = progressBar1.Maximum;
                            }
                        }
                    }
                    formerOpenStream.Close();
                    toFileOpenStream.Close();
                    formerOpenStream.Dispose();
                    toFileOpenStream.Dispose();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("SFileToDFile 3\n" + ex.Message);
                    return false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("SFileToDFile 1\n" + ex.Message);
                return false;
            }
            return true;
        }
    }
    public static partial class FileTool
    {
        /// <summary>
        /// 每次拷贝的文件大小被除数
        /// </summary>
        const int TranSize = 1024 * 1024 * 4;
        /// <summary>
        /// 计算一个文件的进度条大小
        /// </summary>
        /// <param name="formerOpenStream"></param>
        /// <param name="tranSize"></param>
        /// <returns></returns>
        static int Jisuan(FileStream formerOpenStream, int tranSize)
        {
            // 根据一次传输的大小，计算最大传输个数. 
            // Math.Ceiling 方法 (Double),返回大于或等于指定的双精度浮点数的最小整数值
            return Convert.ToInt32(Math.Ceiling(formerOpenStream.Length / (double)tranSize));
        }
        /// <summary>
        /// 获取来源所有文件大小
        /// </summary>
        /// <param name="spath">来源路径</param>
        /// <param name="daxiao">返回所有文件的大小</param>
        public static void GetAllFileLength(string spath, ref int daxiao)//int可能会爆
        {
            DirectoryInfo dir = new DirectoryInfo(spath);
            //获取本文件夹所有文件
            var fil = dir.GetFiles();
            foreach (FileInfo f in fil)
            {
                try
                {
                    //以只读方式打开源文件  
                    FileStream formerOpenStream = new FileStream(f.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    daxiao += Jisuan(formerOpenStream, TranSize);
                    formerOpenStream.Flush();
                    formerOpenStream.Close();
                    formerOpenStream.Dispose();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("GetAllFileLength A01\n" + ex.Message);
                }
            }
            //获取子文件夹内的文件列表,递归遍历
            var dii = dir.GetDirectories();
            foreach (DirectoryInfo d in dii)
            {
                GetAllFileLength(d.FullName, ref daxiao);
            }
        }
    }
    public static partial class FileTool
    {
        /// <summary>
        /// 删除空白文件夹
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns>成功true,失败false</returns>
        public static bool DelFolder(string path)
        {
            bool flag = false;
            try
            {
                if (Directory.Exists(path))
                {
                    var aa = new DirectoryInfo(path);
                    aa.Attributes = FileAttributes.Normal;//设置文件夹属性为普通
                    aa.Delete();
                    flag = true;
                }
            }
            catch
            { }
            return flag;
        }
        /// <summary>
        /// 不存在就新建文件夹
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns>成功true,失败false</returns>
        public static bool NewFolder(string path)
        {
            bool flag = false;
            try
            {
                if (!Directory.Exists(path))
                {
                    DirectoryInfo aa = Directory.CreateDirectory(path);//新建文件夹
                    aa.Attributes = FileAttributes.Normal;//设置文件夹属性为普通
                    flag = true;
                }
            }
            catch
            { }
            return flag;
        }
        /// <summary>
        /// 重命名文件名字,如果路径还存在就名字+1
        /// </summary>
        /// <param name="path">文件路径</param>     
        /// <returns>返回最终的名字,文件不在返回""</returns>
        public static string RenameFile(string path)
        {
            string str = path;
            if (File.Exists(str))
            {
                int a = 1;
                try
                {
                    var dir = new FileInfo(str)
                    {
                        Attributes = FileAttributes.Normal //设置为普通文件   
                    };
                    string qianzhList = dir.DirectoryName + "\\"; // "D:\\K01.惊惊连盒\\03.用户配置" 
                    while (true)
                    {
                        string name = Path.GetFileNameWithoutExtension(path);
                        string pathFull = qianzhList + name + a.ToString() + dir.Extension;
                        if (!File.Exists(pathFull))//如果没有这个文件
                        {
                            dir.MoveTo(pathFull);//就重命名这个文件名
                            str = pathFull;
                            break;
                        }
                        else
                        {
                            a++;
                        }
                    }
                }
                catch
                {
                    throw new Exception("RenameFile重命名文件名出错");
                }
            }
            return str;
        }
        /// <summary>
        /// 路径中包含某个文件夹,有就返回文件夹路径
        /// </summary>
        /// <param name="dwgPath">路径</param>
        /// <param name="name">文件夹名称</param>
        /// <returns>成功返回含有这个文件夹名称的路径,失败返回""</returns>
        public static string GetPathIncludeString(string dwgPath, string name)
        {
            //遍历路径中第几级有"01.饰施图"
            char ca = '\\';
            var dwgPaths = dwgPath.Split(ca);
            var st = new List<string>();
            for (int i = 0; i < dwgPaths.Length; i++)
            {
                if (dwgPaths[i] == name)
                {
                    break;
                }
                else
                {
                    st.Add(dwgPaths[i]);//把前面的路径合并起来
                }
            }
            //如果两个数组相同,表示路径没有"01.饰施图"  
            string x = "";
            if (st.Count != dwgPaths.Length)
            {
                foreach (string item in st)
                {
                    x += item + "\\";
                }
                x += name;
            }
            return x;
        }
        /// <summary>
        /// 列出路径文件,过滤为目标后缀
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="searchPattern">获取后缀的文件</param>
        /// <returns></returns>
        public static List<string> GetThisFolderFiles(string path, string searchPattern = "*.txt")
        {
            var list = new List<string>();
            var theFolder = new DirectoryInfo(path);
            var thefileInfo = theFolder.GetFiles(searchPattern, SearchOption.TopDirectoryOnly);//仅本目录
            foreach (FileInfo NextFile in thefileInfo)  //遍历文件
            {
                list.Add(NextFile.FullName);
            }
            return list;
        }
        /// <summary>
        /// 获取路径下所有文件以及子文件夹中文件
        /// </summary>
        /// <param name="path">全路径根目录</param> 
        /// <param name="extension">后缀名.dwg</param> 
        /// <returns></returns>
        public static List<string> GetFiles(string path, string extension = null)
        {
            var pas = new List<string>();
            GetFiles(path, extension, pas);
            return pas;
        }
        /// <summary>
        /// 获取路径下所有文件以及子文件夹中文件
        /// </summary>
        /// <param name="path">全路径根目录</param> 
        /// <param name="extension">后缀名.dwg</param> 
        /// <param name="pas">传入集合</param> 
        /// <returns></returns>
        private static void GetFiles(string path, string extension, List<string> pas)
        {
            var dir = new DirectoryInfo(path);
            //获取本文件夹所有文件
            var fil = dir.GetFiles();
            foreach (FileInfo f in fil)
            {
                if (string.IsNullOrEmpty(extension))
                {
                    pas.Add(f.FullName);//保存文件路径到表中
                }
                else if (f.Extension.ToUpper() == extension.ToUpper())
                {
                    pas.Add(f.FullName);//保存文件路径到表中
                }
            }
            //获取子文件夹内的文件列表,递归遍历
            var dii = dir.GetDirectories();
            foreach (DirectoryInfo d in dii)
            {
                GetFiles(d.FullName, extension, pas);
            }
        }
        /// <summary>
        /// 判断文件是否被程序占用
        /// </summary>
        /// <param name="fileName">文件路径</param>
        /// <returns>true表示正在使用,false没有使用</returns>
        public static bool IsFileInUse(string fileName)
        {
            bool inUse = true;
            if (File.Exists(fileName))
            {
                FileStream fs = null;
                try
                {
                    fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None);
                    inUse = false;
                }
                catch
                { }
                finally
                {
                    if (fs != null)
                    {
                        fs.Close();
                    }
                }
                return inUse;
            }
            else
            {
                return false;//文件不存在,肯定没有被使用 
            }
        }
    }
}
